package com.github.maojx0630.wechat.bot.reverse;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.zhxu.okhttps.HTTP;
import cn.zhxu.okhttps.WebSocket;
import cn.zhxu.okhttps.fastjson2.Fastjson2MsgConvertor;
import com.alibaba.fastjson2.JSONObject;
import com.github.maojx0630.wechat.bot.common.TempUtil;
import com.github.maojx0630.wechat.bot.config.WechatConfig;
import com.github.maojx0630.wechat.bot.dto.ImageParam;
import com.github.maojx0630.wechat.bot.dto.TextParam;
import com.github.maojx0630.wechat.bot.monitor.WechatUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author 毛家兴
 * @since 2024-04-17 11:49
 */
@Slf4j
@Component
public class WebsocketComponent {

  private final HTTP http;

  private final String ws;

  private final String wxid;

  private final String token;

  private WebSocket webSocket;

  private final WechatUtil wechatUtil;
  private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);


  public WebsocketComponent(WechatConfig config, WechatUtil wechatUtil) {
    if (StrUtil.isBlank(config.getWs())) {
      throw new RuntimeException("反向websocket地址不能为空");
    }

    this.ws = config.getWs();
    this.wechatUtil = wechatUtil;
    this.token = config.getToken();
    this.wxid = wechatUtil.userInfo();
    this.http = HTTP.builder().addMsgConvertor(new Fastjson2MsgConvertor()).build();
    reconnect();
  }

  public void send(String text) {
    if (webSocket != null && webSocket.status() == 1) {
      log.info("向反向代理发送消息 : {}", text);
      webSocket.send(text);
    }
  }

  private void reconnect() {
    this.webSocket =
        this.http
            .webSocket(ws)
            .addHeader("wxid", wxid)
            .addHeader("token", token)
            .setOnOpen(
                (ws, data) -> {
                  log.info("连接成功 : {}", data);
                  executorService.scheduleAtFixedRate(()->send(" heartbeat"),0,5, TimeUnit.SECONDS);
                })
            .setOnClosed(
                (ws, data) -> {
                  log.info("连接关闭 : {}", data);
                  executorService.shutdown();
                  ThreadUtil.execute(
                      () -> {
                        ThreadUtil.sleep(1000L);
                        log.info("等待一秒尝试重连");
                        reconnect();
                      });
                })
            .setOnException(
                (ws, data) -> {
                  log.error("连接异常 : ", data);
                })
            .setOnMessage(
                (ws, data) -> {
                  String dataStr = data.toString();
                  JSONObject jsonObject = JSONObject.parseObject(dataStr);
                  if (dataStr.length() > 200) {
                    log.info("收到消息 : {} ......", dataStr.substring(0, 200));
                  } else {
                    log.info("收到消息 : {}", data);
                  }
                  String type = jsonObject.getString("type");
                  if ("text".equals(type)) {
                    TextParam param = jsonObject.getObject("data", TextParam.class);
                    wechatUtil.sendText(param);
                  } else if ("image".equals(type)) {
                    ImageParam param = jsonObject.getObject("data", ImageParam.class);
                    if(dataStr.length()>1250000){
                      File file=TempUtil.getTempFile("jpg");
                      Base64.decodeToFile(param.getImage(),file);
                      param.setImage(null);
                      param.setPath(file.getAbsolutePath());
                    }

                    wechatUtil.sendImage(param);
                  }
                })
            .listen();
  }
}
